package com.test.chatdemo.controller;

import com.test.chatdemo.pojo.NewUser;
import com.test.chatdemo.service.ChatHistoryRepository;
import com.test.chatdemo.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.RestController;
import com.test.chatdemo.pojo.Result;
import com.test.chatdemo.pojo.User;
import com.test.chatdemo.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RequiredArgsConstructor
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private ChatClient chatClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ChatHistoryRepository chatHistoryRepository;

    private static final Logger log = LoggerFactory.getLogger(UserController.class);

    /**
     * 注册
     */
    @PostMapping("/register")
    public Result<User> register(@RequestBody User user) {
        log.info("用户注册：{}", user);

        // 参数校验
        if (user.getCode() == null || user.getCode().trim().isEmpty()) {
            return Result.error("验证码不能为空");
        }

        // 验证码校验（不区分大小写）
        String captchaCode = user.getCode().trim().toLowerCase();
        String redisKey = "captcha_code:" + captchaCode;

        log.info("验证码验证，用户输入: {}, Redis key: {}", user.getCode(), redisKey);

        String captcha = stringRedisTemplate.opsForValue().get(redisKey);
        log.info("从Redis获取的验证码状态: {}", captcha);

        if (captcha == null) {
            return Result.error("验证码错误或已过期");
        }

        // 验证通过后删除Redis中的验证码（防止重复使用）
        stringRedisTemplate.delete(redisKey);

        //验证用户是否存在
        String name =userService.getUserName(user);
        if(name != null) {
            return Result.error("当前用户名已存在");
        }

        //对密码进行加密
        String password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        user.setPassword(password);

        userService.register(user);

        return Result.success("注册成功");
    }

    /**
     * 登录 - 验证码验证
     */
    @PostMapping("/login")
    public Result login(@RequestBody User user) {
        log.info("用户登录：{}", user);

        // 参数校验
        if (user.getCode() == null || user.getCode().trim().isEmpty()) {
            return Result.error("验证码不能为空");
        }

        //对密码进行加密
        String password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        user.setPassword(password);

        // 验证码校验（不区分大小写）
        String captchaCode = user.getCode().trim().toLowerCase();
        String redisKey = "captcha_code:" + captchaCode;

        log.info("验证码验证，用户输入: {}, Redis key: {}", user.getCode(), redisKey);

        String captcha = stringRedisTemplate.opsForValue().get(redisKey);
        log.info("从Redis获取的验证码状态: {}", captcha);

        if (captcha == null) {
            return Result.error("验证码错误或已过期");
        }

        // 验证通过后删除Redis中的验证码（防止重复使用）
        stringRedisTemplate.delete(redisKey);

        // 用户登录验证
        User getUser = userService.login(user);
        Integer id = getUser.getId();

        if (getUser != null) {
            Map<String,Object> claims = new HashMap<>();

            claims.put("id", id);
            claims.put("name", getUser.getName());
            claims.put("username", getUser.getPassword());

            //生成jwt令牌，存到redis中12小时
            String jwt = JwtUtils.generateJwt(claims);
            stringRedisTemplate.opsForValue().set(jwt,"token" + id,12, TimeUnit.HOURS);

            return Result.success(jwt);
        }

        return Result.error("用户名或密码错误");
    }

    @PutMapping("/changePassword")
    public Result changePassword(@RequestBody NewUser newUser, @RequestHeader("token") String token) {
        try {
            // 从JWT令牌中解析用户信息
            io.jsonwebtoken.Claims claims = JwtUtils.parseJWT(token);
            String username = (String) claims.get("name");

            // 设置用户名
            newUser.setName(username);

            User user = new User();
            BeanUtils.copyProperties(newUser, user);

            String password1 = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
            user.setPassword(password1);

            // 对密码进行加密
            String password = DigestUtils.md5DigestAsHex(newUser.getPassword().getBytes());
            newUser.setPassword(password);

            String newPassword = DigestUtils.md5DigestAsHex(newUser.getNewPassword().getBytes());
            newUser.setNewPassword(newPassword);

            User nowUser = userService.getUser(user);
            if (nowUser == null) {
                return Result.error("原密码错误");
            }

            // 修改密码，修改后删除原本的jwt，生成新的jwt令牌
            userService.changePassword(newUser);

            // 删除Redis中旧的JWT令牌
            stringRedisTemplate.delete("token" + nowUser.getId());

            Map<String,Object> newClaims = new HashMap<>();
            newClaims.put("id", nowUser.getId());
            newClaims.put("name", nowUser.getName());
            newClaims.put("username", nowUser.getPassword());

            // 生成新的jwt令牌
            String jwt = JwtUtils.generateJwt(newClaims);

            return Result.success("修改密码成功");
        } catch (Exception e) {
            log.error("修改密码失败", e);
            return Result.error("修改密码失败");
        }
    }

    @GetMapping(value ="/chat", produces = "text/html;charset=utf-8")
    public Flux<String> chat(String msg, String chatId) {
        chatHistoryRepository.save("chat", chatId);
        return chatClient.prompt()
                .user(msg)
                .advisors(a -> a.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
                .stream()
                .content();
    }
}